﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

namespace GateKeeper
{
    public static class Whitelist
    {

        private static Boolean findMatch(NodeType nodeType, string value)
        {
            try
            {
                XmlNodeList entryNodes = Utils.xmlWhiteList.SelectNodes(string.Format("/gatekeeper/{0}/entry", nodeType.ToString()));
                foreach (XmlNode node in entryNodes)
                {
                    string pattern = node.Attributes[@nodeType.ToString()].Value;

                    // Need this in case of an empty entry field - empty patterns always return true!
                    if (string.IsNullOrEmpty(pattern)) { return false; }

                    GateKeeperModule.log.DebugFormat("Matching entry : {0} = {1}", value, pattern);
                    if (Regex.IsMatch(value, pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase))
                    {
                        GateKeeperModule.log.DebugFormat("Match found in WhiteList : [{0}]", value);
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                GateKeeperModule.log.WarnFormat("WhiteList | findMatch : [{0}]", ex.Message);
                GateKeeperModule.log.Error(ex.StackTrace);
                return false;
            }
        }

        public static Boolean isWhiteListRequest(HttpContext current)
        {
            onBegin_Check(current);
            // Using try catch in order to ensure eventhandler executes
            try
            {
                // Check if request is for contact page url specified in config file
                if (!string.IsNullOrEmpty(GateKeeperModule.config.ContactFormUrl) &&
                                Regex.IsMatch(current.Request.Url.AbsolutePath, GateKeeperModule.config.ContactFormUrl, RegexOptions.IgnoreCase))
                {
                    GateKeeperModule.log.Debug("Request for ContactPage - let them pass");
                    return true;
                }

                // Check if in IPWhiteList
                if (findMatch(NodeType.ipaddress, current.Request.UserHostAddress)) { return true; }

                // Check if in UAWhiteList
                if (findMatch(NodeType.useragent, current.Request.UserAgent)) { return true; }

                //Check if in UrlWhiteList
                if (findMatch(NodeType.url, current.Request.Url.AbsoluteUri)) { return true; }

                // Request did not match any of the whitelist checks
                return false;
            }
            finally
            { onEnd_Check(current); }
        }

        #region eventhandlers
        public static event EventHandler<EventArgs> Begin_Check;
        private static void onBegin_Check(HttpContext current)
        {
            if (Begin_Check != null)
            {
                GateKeeperModule.log.Debug("Executing Begin_Check eventHandler");
                Begin_Check(current, new EventArgs());
            }
        }

        public static event EventHandler<EventArgs> End_Check;
        private static void onEnd_Check(HttpContext current)
        {
            if (End_Check != null)
            {
                GateKeeperModule.log.Debug("Executing End_Check eventHandler");
                End_Check(current, new EventArgs());
            }
        }
        #endregion //events
    }
}
